﻿using Admin.NET.Core;
using Furion.DatabaseAccessor;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using Mapster;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using MOKA.TPM.Application.Enum;
using MOKA.TPM.Application.Service.Dto;
using MOKA.TPM.Entity;
using MOKA.TPM.Service.Dto;
using MOKA.TPM.Utility.Const;
using SqlSugar;
using System.ComponentModel;

namespace MOKA.TPM.Service;

/// <summary>
/// 系统字典目录服务
/// </summary>
[ApiDescriptionSettings(TPMConst.GroupName, Order = 860)]
public class Service_SysDictCode : IDynamicApiController, ITransient
{
    private readonly SqlSugarRepository<SysDictCode> _rep;
    private readonly UserManager _userManager;
    private IHttpContextAccessor _accessor;//获取请求上下文_userRepository
    private readonly ISqlSugarClient _db;

    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="db"></param>
    /// <param name="rep"></param>
    /// <param name="userManager"></param>
    /// <param name="accessor"></param>
    public Service_SysDictCode(ISqlSugarClient db, SqlSugarRepository<SysDictCode> rep, UserManager userManager, IHttpContextAccessor accessor)
    {
        _db = db;
        _rep = rep;
        _userManager = userManager;
        _accessor = accessor;
    }

    /// <summary>
    /// 获取分页列表 🧩
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "Page"), HttpPost]
    [AllowAnonymous]
    [DisplayName("获取分页列表")]
    public async Task<SqlSugarPagedList<SysDictCodeOutput>> Page(PageSysDictCodeInput input)
    {
        var lists = await _rep.AsTenant().QueryableWithAttr<SysDictCode>()
            .Includes(a => a.sysDictDetail_TPMDeviceGroupId)
            .Includes(a => a.SysDictDetails) //详细表（无字典）
                                             //.LeftJoin<SysDictDetail>((a, b) => a.TPMDeviceGroupId == b.Id)
            .WhereIF(!string.IsNullOrEmpty(input.CatCode?.Trim()), a => a.CatCode.Contains(input.CatCode.Trim())) //唯一索引
            .Where(a => a.IsDelete == false)
            .Select((a) => new SysDictCodeOutput()
            {
                Id = a.Id.SelectAll(),
                TPMDeviceGroupName = a.sysDictDetail_TPMDeviceGroupId.ItemName,//字典
                sysDictDetail_TPMDeviceGroupId = a.sysDictDetail_TPMDeviceGroupId,
                SysDictDetails = a.SysDictDetails, //详细表
            })
            .Mapper((item) =>
            {
                //Mapster映射转换，不能有SQL
                //TypeAdapterConfig config = new TypeAdapterConfig()
                //.ForType<ContractFile, ContractFileOutput>()
                //.IgnoreIf((src, dest) => src.File == null, "Id", "Name", "FileType", "FileName", "Suffix", "FilePath", "SizeKb", "Url")
                //    .Map(dest => dest.Id, src => src.File.Id)
                //    .Map(dest => dest.Name, src => src.File.Id + src.File.Suffix)
                //.Config
                //.ForType<JToken, JToken>()
                //    .MapWith(json => json)
                //.Config;
                //item.ContractBody = item.ContractBodyIn.Adapt<List<ContractFileOutput>>(config);
            })
            .OrderBuilder(input) //(input, "a.", "PartNo", false)
            .ToPagedListAsync(input.Page, input.PageSize);

        //使用.ThenMapper继续查询有字典详细表
        return lists;
    }

    /// <summary>
    /// 获取列表🔖
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "List")]
    [DisplayName("获取列表")]
    [AllowAnonymous]
    public async Task<List<SysDictCodeOutput>> GetList([FromQuery] GetSysDictCodeInput input)
    {
        var lists = await _rep.AsTenant().QueryableWithAttr<SysDictCode>()
            .Includes(a => a.sysDictDetail_TPMDeviceGroupId)
            .Includes(a => a.SysDictDetails) //详细表（无字典）
                                             //.LeftJoin<SysDictDetail>((a, b) => a.TPMDeviceGroupId == b.Id)
            .WhereIF(input.Status.HasValue, a => a.Status == input.Status)
            .Where(a => a.IsDelete == false)
            .OrderBy(a => new { a.CatCode, })
            .Select((a) => new SysDictCodeOutput()
            {
                Id = a.Id.SelectAll(),
                TPMDeviceGroupName = a.sysDictDetail_TPMDeviceGroupId.ItemName,//字典
                sysDictDetail_TPMDeviceGroupId = a.sysDictDetail_TPMDeviceGroupId,
                SysDictDetails = a.SysDictDetails, //详细表
            })
            .Mapper((item) =>
            {
                //Mapster映射转换，不能有SQL
                //TypeAdapterConfig config = new TypeAdapterConfig()
                //.ForType<ContractFile, ContractFileOutput>()
                //.IgnoreIf((src, dest) => src.File == null, "Id", "Name", "FileType", "FileName", "Suffix", "FilePath", "SizeKb", "Url")
                //    .Map(dest => dest.Id, src => src.File.Id)
                //    .Map(dest => dest.Name, src => src.File.Id + src.File.Suffix)
                //.Config
                //.ForType<JToken, JToken>()
                //    .MapWith(json => json)
                //.Config;
                //item.ContractBody = item.ContractBodyIn.Adapt<List<ContractFileOutput>>(config);
            })
            .Take(20)//为了性能，只取20个。
            .ToListAsync();

        //使用.ThenMapper继续查询有字典详细表
        return lists;
    }

    /// <summary>
    /// 获取单个对象
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "One")]
    [DisplayName("获取单个对象")]
    [AllowAnonymous]
    public async Task<SysDictCodeOutput> GetOne([FromQuery] SysDictCodeInput input)
    {
        var lists = await _rep.AsTenant().QueryableWithAttr<SysDictCode>()
            .Includes(a => a.sysDictDetail_TPMDeviceGroupId)
            .Includes(a => a.SysDictDetails) //详细表（无字典）
            //.LeftJoin<FlowStateinfo>((a, d) => a.Id == d.SourceId)
            .WhereIF(!string.IsNullOrEmpty(input.CatCode?.Trim()), a => a.CatCode.Contains(input.CatCode ?? "".Trim())) //唯一索引
            .WhereIF(input.TPMDeviceGroupId.HasValue, a => a.TPMDeviceGroupId == input.TPMDeviceGroupId)
            .WhereIF(input.Id.HasValue, a => a.Id == input.Id)
            .OrderBy(a => new { a.CatCode, })
            .Select((a) => new SysDictCodeOutput()
            {
                Id = a.Id.SelectAll(),
                TPMDeviceGroupName = a.sysDictDetail_TPMDeviceGroupId.ItemName,//字典
                sysDictDetail_TPMDeviceGroupId = a.sysDictDetail_TPMDeviceGroupId,
                SysDictDetails = a.SysDictDetails, //详细表
            })
            .SingleAsync();

        //使用.ThenMapper继续查询有字典详细表
        return lists;
    }

    /// <summary>
    /// 添加 🧩
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "Add"), HttpPost]
    [DisplayName("添加")]
    [AllowAnonymous]
    public async Task<bool> AddData(AddSysDictCodeInput input)
    {
        var isExist = await _rep.IsAnyAsync(u => u.CatCode == input.CatCode && u.TPMDeviceGroupId == input.TPMDeviceGroupId); //唯一索引是否存在
        if (isExist)
        {
            throw Oops.Oh(TpmErrorCodeEnum.FieldValueExisted, "字典代码", input.CatCode + "设备组ID", input.TPMDeviceGroupId);
        }

        var entity = input.Adapt<SysDictCode>(); //将AddSysDictCodeInput转成SysDictCode

        //entity.Code = "thisCode"; //后台生成字段值

        //启动事务
        using (var uow = _db.CreateContext())
        {
            var ret = await _rep.AsInsertable(entity).EnableDiffLogEvent().ExecuteReturnEntityAsync();//插入后返回实体

            //插入详细表
            foreach (var item in entity.SysDictDetails)
            {
                item.DictCodeID = ret.Id;
            }
            SqlSugarRepository<SysDictDetail> _repSysDictDetail = _rep.ChangeRepository<SqlSugarRepository<SysDictDetail>>();
            await _repSysDictDetail.InsertRangeAsync(entity.SysDictDetails);//批量插入

            //提交事务
            uow.Commit();
            return ret != null;
        }
    }

    /// <summary>
    /// 更新 🧩
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "Update"), HttpPost]
    [DisplayName("更新")]
    [AllowAnonymous]
    public async Task<bool> UpdateData(UpdateSysDictCodeInput input)
    {
        //主键是否存在
        var isExist = await _rep.IsAnyAsync(u => u.Id == input.Id);
        if (!isExist)
            throw Oops.Oh(TpmErrorCodeEnum.FieldValueNotExist, "Id", input.Id);

        isExist = await _rep.IsAnyAsync(u => u.CatCode == input.CatCode && u.TPMDeviceGroupId == input.TPMDeviceGroupId && u.Id != input.Id); //唯一索引是否存在
        if (isExist)
        {
            throw Oops.Oh(TpmErrorCodeEnum.FieldValueExisted, "字典代码", input.CatCode + "设备组ID", input.TPMDeviceGroupId);
        }
        var entity = input.Adapt<SysDictCode>(); //将UpdateSysDictCodeInput转成SysDictCode

        //启动事务
        using (var uow = _db.CreateContext())
        {
            bool ret = await _rep.AsUpdateable(entity).IgnoreNullColumns().EnableDiffLogEvent().ExecuteCommandAsync() > 0;

            //更新详细表
            foreach (var item in entity.SysDictDetails)
            {
                item.DictCodeID = entity.Id;
            }
            SqlSugarRepository<SysDictDetail> _repSysDictDetail = _rep.ChangeRepository<SqlSugarRepository<SysDictDetail>>();
            await _repSysDictDetail.AsDeleteable().Where(it => it.DictCodeID == entity.Id).ExecuteCommandAsync();//全删除
            await _repSysDictDetail.InsertRangeAsync(entity.SysDictDetails);//批量插入

            //提交事务
            uow.Commit();
            return ret;
        }
    }

    /// <summary>
    /// 删除 🧩
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "Delete"), HttpPost]
    [DisplayName("删除")]
    [AllowAnonymous]
    public async Task<bool> DeleteData(DeleteSysDictCodeInput input)
    {
        var entity = await _rep.GetFirstAsync(u => u.Id == input.Id) ?? throw Oops.Oh(TpmErrorCodeEnum.FieldValueNotExist, "Id", input.Id);

        //启动事务
        using (var uow = _db.CreateContext())
        {
            //真正删除详细表
            SqlSugarRepository<SysDictDetail> _repSysDictDetail = _rep.ChangeRepository<SqlSugarRepository<SysDictDetail>>();
            await _repSysDictDetail.AsDeleteable().Where(it => it.DictCodeID == entity.Id).ExecuteCommandAsync();//全删除
            bool ret = await _rep.Context.Deleteable(entity).EnableDiffLogEvent().ExecuteCommandAsync() > 0;

            //提交事务
            uow.Commit();
            return ret;
        }
    }

    /// <summary>
    /// 修改部分数据 🔖
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "UpdateSome"), HttpPost]
    [DisplayName("修改部分数据")]
    [AllowAnonymous]
    public async Task<bool> UpdateSomeData(UpdateSomeSysDictCodeInput input)
    {
        //主键是否存在
        var isExist = await _rep.IsAnyAsync(u => u.Id == input.Id);
        if (!isExist)
        {
            throw Oops.Oh(TpmErrorCodeEnum.FieldValueNotExist, "Id", input.Id);
        }

        var entity = input.Adapt<SysDictCode>(); //将UpdateSysDictCodeInput转成SysDictCode

        //启动事务
        using (var uow = _db.CreateContext())
        {
            bool ret = await _rep.AsUpdateable(entity).UpdateColumns(it => new { it.Status, }).ExecuteCommandAsync() > 0;

            //提交事务
            uow.Commit();
            return ret;
        }
    }

    /// <summary>
    /// 批量添加
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "AddRange"), HttpPost]
    [DisplayName("批量添加")]
    [AllowAnonymous]
    public async Task<int> AddBulkData(List<SysDictCode> input)
    {
        foreach (var item in input)
        {
            var isExist = await _rep.IsAnyAsync(u => u.CatCode == item.CatCode && u.TPMDeviceGroupId == item.TPMDeviceGroupId); //唯一索引是否存在
            if (isExist)
            {
                throw Oops.Oh(TpmErrorCodeEnum.FieldValueExisted, "字典代码", item.CatCode + "设备组ID", item.TPMDeviceGroupId);
            }
        }

        //启动事务
        using (var uow = _db.CreateContext())
        {
            int ret = await _rep.Context.Insertable(input).ExecuteCommandAsync();
            //不需要上传详细表了

            //提交事务
            uow.Commit();
            return ret;
        }
    }
}